ScrumJsonReader = Ext.extend(Ext.data.JsonReader, {
    constructor: function(meta, recordType) {
    	meta = meta || {root: 'root'};
    	recordType = recordType || [];
    	meta.root = meta.root || 'root';
    	ScrumJsonReader.superclass.constructor.call(this, meta, recordType);
    }
});

ScrumXmlReader = Ext.extend(Ext.data.XmlReader, {
    constructor: function(meta, recordType) {
    	meta = meta || {record: 'Item', id: '@id', totalRecords: '@total'};
    	recordType = recordType || [];
    	meta.record = meta.record || 'Item';
    	meta.id = meta.id || '@id';
    	meta.totalRecords = meta.totalRecords || '@total';
    	ScrumJsonReader.superclass.constructor.call(this, meta, recordType);
    }
});

ScrumJsonWriter = Ext.extend(Ext.data.JsonWriter, {
    constructor: function (config) {
        config = config || {};
        config = Ext.apply({
            encode: true,
            writeAllFields: false
        }, config);
        ScrumJsonWriter.superclass.constructor.call(this, config);
    },

    destroyRecord: function (rec) {
        return rec.data;
    }
});

ScrumProxy = Ext.extend(Ext.data.HttpProxy, {
    constructor: function(config) {
    	config = config || {};
        ScrumProxy.superclass.constructor.call(this, config);        
    }
});

ScrumStore = Ext.extend(Ext.data.GroupingStore, {
    constructor: function(config) {
    	config = config || {};
    	if(config.readerConfig){
    		var reader;
    		if(!config.readerConfig.type || config.readerConfig.type == 'json'){
    			reader = new ScrumJsonReader(null, config.readerConfig.recordType);
    		}
    		else if(config.readerConfig.type == 'xml'){
    			reader = new ScrumXmlReader(null, config.readerConfig.recordType);
    		}
    		config = Ext.apply({reader: reader}, config);
        }
        if (config.writerConfig) {
            var writer = new ScrumJsonWriter(config.writerConfig); 
    		config = Ext.apply({writer: writer}, config);
        }
	    if(config.proxyConfig && !config.url){
            var proxy = new ScrumProxy(config.proxyConfig);
    		config = Ext.apply({proxy: proxy}, config);
        }
        var listeners = {
        };
    config = Ext.apply({ autoSave: false, batch: true }, config);
        ScrumStore.superclass.constructor.call(this, config);        
    }
});

ScrumArrayStore = Ext.extend(Ext.data.ArrayStore, {
    constructor: function (config) {
        config = config || {};
        if (config.readerConfig) {
            var reader;
            if (!config.readerConfig.type || config.readerConfig.type == 'json') {
                reader = new ScrumJsonReader(null, config.readerConfig.recordType);
            }
            else if (config.readerConfig.type == 'xml') {
                reader = new ScrumXmlReader(null, config.readerConfig.recordType);
            }
            config = Ext.apply({ reader: reader }, config);
        }
        config = Ext.apply({ autoDestroy: true, idIndex: 0, fields: ['value','display'] }, config);
        ScrumArrayStore.superclass.constructor.call(this, config);
    }
});

ScrumColumnModel = Ext.extend(Ext.grid.ColumnModel, {
    constructor: function (config) {
        config = config || {};
        if (config.columns) {
            for (var i = 0; i < config.columns.length; i++) {
                var column = config.columns[i];
                if (!column.editor) {
                    var editorField;
                    if ((!column.type && !column.xtype) || column.type == 'string') {
                        editorField = new Ext.form.TextField({ allowBlank: true });
                    }
                    else if (column.type == 'boolean') {
                        editorField = new Ext.form.Checkbox({ checked: true });
                        column.width = 50;
                    }
                    else if (column.type == 'date' || column.xtype == 'datecolumn') {
                        editorField = new Ext.form.DateField({ allowBlank: true, xtype: 'datefield', format: 'Y-m-d', altFormats: 'Y-m-d' });
                        column.width = 100;
                    }
                    else if (column.type == 'time') {
                        editorField = new Ext.form.TimeField({ allowBlank: true });
                    }
                    else if (column.type == 'combo') {
                        var store = new ScrumArrayStore();
                        editorField = new ScrumComboBox({
                            store: store
                        });
                        column.width = 100;
                    }
                    column = Ext.apply({ editor: editorField }, column);
                    config.columns[i] = column;
                }
                config.columns[i].width = config.columns[i].width || 80;
            }
            //config.columns.unshift(new Ext.grid.CheckboxSelectionModel());
            config.columns.unshift({ header: 'Actions', renderer: { fn: renderLink.renderActionLinks, scope: this} });
            config.columns.unshift(new Ext.grid.RowNumberer({ header: 'Order#' }));
        }
        var defaults = { sortable: true };
        config = Ext.apply({ defaults: defaults }, config);
        ScrumColumnModel.superclass.constructor.call(this, config);
    }
});

ScrumView = Ext.extend(Ext.grid.GroupingView, {
    constructor: function(config) {
    	config = config || {};
        config = Ext.apply({
            forceFit: false,
            groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
        }, config);
        ScrumView.superclass.constructor.call(this, config);
    }
});

ScrumComboBox = Ext.extend(Ext.form.ComboBox, {
    constructor: function (config) {
        config = config || {};
        config = Ext.apply({
            typeAhead: false,
            hideTrigger: false,
            forceSelection: true,
            selectOnFocus: true,
            mode: 'local',
            triggerAction: 'all',
            lazyRender: true,
            allowBlank: true,
            displayField: 'display',
            valueField: 'value',
            record: {}
        }, config);
        ScrumComboBox.superclass.constructor.call(this, config);
    }
});

ScrumFormPanel = Ext.extend(Ext.FormPanel, {
    constructor: function(config) {
    	config = config || {};
        config = Ext.apply({
        labelWidth: 75, 
        frame: true,
        bodyStyle:'padding:5px 5px 0',
        width: 300,
        defaults: {width: 230},
        defaultType: 'textfield'
        }, config);
        ScrumFormPanel.superclass.constructor.call(this, config);
    } 
});

ScrumFormWindow = Ext.extend(Ext.Window, {
    constructor: function(config) {
    	config = config || {};
        //var store = new ScrumStore({proxyConfig: {url: config.url}}); 
        formConfig = config.formConfig || {};
        formConfig = Ext.apply({
            buttons: [{text: 'Save', handler: ''},{text: 'Cancel', handler: ''}]
        }, formConfig);
        var formP = new ScrumFormPanel(formConfig); 
        config = Ext.apply({
            applyTo:'newPw',
            layout:'fit',
            width:500,
            height:300,
            closeAction:'hide',
            plain: true,
            items: [formP]
            //store:store
        }, config);
        ScrumFormWindow.superclass.constructor.call(this, config);
    }
});

ScrumEditorGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
    constructor: function (config) {
        config = config || {};
        if (config.storeConfig) {
            /*var listeners = {
            'load': function () {
            var gridPanel = Ext.getCmp('grid-panel');
            alert(gridPanel);
            for (var i = 0; i < gridPanel.colModel.columns.length; i++) {
            var column = gridPanel.colModel.columns[i];
            if (column.type == 'combo') {
            var store = new ScrumArrayStore();
            var data = eval(gridPanel.store.data.items[0].json[column.dataIndex].candidateValue);
            store.loadData(data);
            gridPanel.colModel.columns[i].editor = new ScrumComboBox({ store: store });
            }
            }
            }
            };
            config.storeConfig = Ext.apply({ listeners: listeners }, config.storeConfig);*/
            var store = new ScrumStore(config.storeConfig);
            config = Ext.apply({ store: store }, config);
        }
        if (config.cmConfig && config.cmConfig.columns) {
            config.cmConfig = Ext.apply({ store: store }, config.cmConfig);
            var cm = new ScrumColumnModel(config.cmConfig);
            config = Ext.apply({ cm: cm }, config);
        }
        config.newPwConfig = config.newPwConfig || {};
        config = Ext.apply({
            region: 'center',
            width: 1200,
            height: 400,
            clicksToEdit: 2,
            view: new ScrumView({})
        }, config);
        ScrumEditorGridPanel.superclass.constructor.call(this, config);
    },
    newPw: '',
    initComponent: function () {
        // relay the Store's CRUD events into this grid so these events can be conveniently listened-to in our application-code.
        this.relayEvents(this.store, ['destroy', 'save', 'update']);
        this.tbar = this.buildTopToolbar();
        this.bbar = this.buildBottomToolbar();
        this.buttons = this.buildButtons();
        this.newPw = this.newPopupWindow();
        ScrumEditorGridPanel.superclass.initComponent.call(this);
    },
    buildTopToolbar: function () {
        return [{ text: 'New', handler: this.onNew, scope: this }, '-',
            { text: 'Insert', iconCls: 'silk-add', handler: this.onInsert, scope: this }, '-',
            { text: 'Save', iconCls: 'silk-add', handler: this.onSave, scope: this }, '-',
            { text: 'Delete', iconCls: 'silk-delete', handler: this.onDelete, scope: this }, '-',
            { text: 'Refresh', handler: this.onRefresh, scope: this }, '-'
        ];
    },
    buildBottomToolbar: function () {
        return ['<b>@Config:</b>', '-',
            { text: 'autoSave', enableToggle: true, pressed: true,
                toggleHandler: function (btn, pressed) { this.store.autoSave = pressed; },
                scope: this
            },
            '-',
            { text: 'batch', enableToggle: true, pressed: true,
                toggleHandler: function (btn, pressed) { this.store.batch = pressed; },
                scope: this
            },
            '-'];
    },
    buildButtons: function () {
        return [{ text: 'Save', iconCls: 'icon-save', handler: this.onSave, scope: this}];
    },
    newPopupWindow: function () {
        var newPw = new ScrumFormWindow({
            buttons: [{ text: 'Close', handler: function () { newPw.hide(); } }],
            formConfig: this.newPwConfig.formConfig
        });
        return newPw;
    },
    onNew: function (btn, ev) {
        var u = new this.store.recordType({});
        this.newPw.show();
        this.stopEditing();
    },
    onInsert: function (btn, ev) {
        var u = new this.store.recordType({});
        this.stopEditing();
        this.store.insert(0, u);
        this.startEditing(0, 1);
    },
    onDelete: function (btn, ev) {
        var index = this.getSelectionModel().getSelectedCell();
        if (!index) {
            return false;
        }
        var rec = this.store.getAt(index[0]);
        this.store.remove(rec);
        this.store.doTransaction('destroy', rec, this.store.batch);
    },
    onRefresh: function (btn, ev) {
        this.store.reload();
    },
    onSave: function (btn, ev) {
        this.store.save();
        this.store.reload();
    },
    show: function () {
        this.store.load();
    }
});

ScrumViewport = Ext.extend(Ext.Viewport, {
    constructor: function(config) {
    	config = config || {};
        config = Ext.apply({
        }, config);
        ScrumViewport.superclass.constructor.call(this, config);
    }
});

var renderLink = {
    renderActionLinks: function (val, metaData, record, rowIndex, colIndex, store) {
        var linkText = '';
        linkText = '<a href="' + record.data.objecttype + 'View.html?id=' + record.data.id + '&retUrl=' + window.location + '">View</a>';
        linkText += '&nbsp;&#124;&nbsp;<a href="'+ record.data.objecttype + 'Edit.html?id=' + record.data.id + '&retUrl=' + window.location + '">Edit</a>';
        return linkText;
    },
    renderTitleLink: function (val, metaData, record, rowIndex, colIndex, store) {
        var oldUrl = window.location.href;
        var newUrl = "";
        var paramIndex = oldUrl.indexOf('startIndex=');
        if (paramIndex != -1) {
            newUrl = oldUrl.substring(0, paramIndex + 11) + (record.data['IndexNumber'] - 1 - rowIndex);
        }
        else if (record.data['IndexNumber'] != undefined) {
            newUrl = oldUrl + '?startIndex=' + (record.data['IndexNumber'] - 1 - rowIndex);
        }
        else {
            newUrl = oldUrl;
        }

        var entityCode = record.data['entityCode']; // This is a reference field of json record, it can be Story ID or Task ID.
        var idTooltip = '';
        if (entityCode != null && entityCode != '') {
            idTooltip = entityCode + '&nbsp;:&nbsp;&nbsp;';
        }
        var tooltp = idTooltip + val;
        if (typeof val == 'undefined') {
            return '';
        }
        var linkText = '<a href="/' + record.data['Id'] + '?retUrl=' + newUrl + '" title="' + tooltp + '" >' + val + '</a>';
        return linkText;
    },
    renderIdLink: function (val, metaData, record, rowIndex, colIndex, store) {
        var oldUrl = window.location.href;
        var newUrl = "";
        var paramIndex = oldUrl.indexOf('startIndex=');
        if (paramIndex != -1) {
            newUrl = oldUrl.substring(0, paramIndex + 11) + (record.data['IndexNumber'] - 1);
        }
        else if (record.data['IndexNumber'] != undefined) {
            newUrl = oldUrl + '?startIndex=' + (record.data['IndexNumber'] - 1);
        }
        else {
            newUrl = oldUrl;
        }

        var linkText = '<a href="/' + record.data['Id'] + '?retUrl=' + newUrl + '">' + val + '</a>';
        return linkText;
    }
};
